#include "EffetBois.hpp"

#include "Melange.hpp"

#include "Bruit/perlin.hpp"

#include <cmath>

using namespace std;
using namespace boost::assign;

/**
 * Constructeur standard, permet d'initialiser les champs de la classe
 * mère et le champ Multiplicateur.
 *
 * La version par défaut crée un motif à base de noir et de blanc.
 *                                                                             
 * @param refl coefficient de réflexion.
 * @param trans coefficient de transparence.
 * @param indice indice de réfraction.
 * @param reg coefficient de diffusion.
 * @param couleurs conteneur des instances de Couleur à utiliser.
 * @param coeff intensité de la perturbation.
 * @param mult coefficient multiplicatif du bruit.
 */
EffetBois::EffetBois(const double& refl, const double& trans,
		     const double& indice, const double& reg, 
		     const vector< Couleur >& couleurs,
		     const double& coeff, const double& mult)
  : EffetBase( refl, trans, indice, reg, couleurs, list_of( 0. ), coeff ),
    Multiplicateur( mult )
{
  Colors.resize( 2 );

  Type = tEffetBois;
}

/**
 * Constructeur initialisant tous les champs de la structure, avec en
 * plus une perturbation sur la normale.
 *
 *                                                                             
 * @param refl coefficient de réflexion.
 * @param trans coefficient de transparence.
 * @param indice indice de réfraction.
 * @param reg coefficient de diffusion.
 * @param bruit perturbation sur la normale.
 * @param couleurs conteneur des instances de Couleur à utiliser.
 * @param coeff intensité de la perturbation.
 * @param mult coefficient multiplicatif du bruit.
 */
EffetBois::EffetBois(const double& refl, const double& trans,
		     const double& indice, const double& reg, 
		     const double& bruit, 
		     const vector< Couleur >& couleurs,
		     const double& coeff, const double& mult)
  : EffetBase( refl, trans, indice, reg, bruit, couleurs, list_of( 0. ),
	       coeff ), Multiplicateur( mult )
{
  Colors.resize( 2 );

  Type = tEffetBois;
}

/**
 * Le destructeur n'a rien de spécial à faire.
 */
EffetBois::~EffetBois()
{}

/**
 * Modifie la valeur de Color à partir du bruit généré pour le point
 * de la surface donné.
 *
 * @param pt point pour lequel on veut obtenir le mélange de couleurs.
 * @return une référence constante sur Color.
 */
Couleur EffetBois::couleur(const Coord& pt)
{
  double val( valeurBruit( pt ) );

  vector< double > poids = list_of( val )( 1. - val );

  return faireMelangeCouleurs( Colors, poids );
}

/**
 * On multiplie premièrement pt par Coefficient (permet d'avoir le
 * même motif à différentes échelles), puis on calcule \f[ M \,
 * \operatorname{bruit} \left( x, y, z \right)\f]. La valeur retournée
 * est finalement ramenée dans l'intervalle [0,1] en soustrayant la
 * partie entière.
 */
double EffetBois::valeurBruit(const Coord& pt) const
{
  Coord p( pt );                                                                
  p *= Coefficient;
  double val( Multiplicateur * noise( p.x(), p.y(), p.z() ) );
  return val - floor( val );
}
